﻿using ActionSystem.Core.ActiveLogic;
using ActionSystem.Core.AnimationLogic;
using ActionSystem.Core.HitLogic;
using ActionSystem.Core.PhysicsLogic;
using ActionSystem.Core.Utils;
using System.Collections.Generic;
using UnityEngine;
using XMLib;

namespace ActionSystem.Core
{
    [DefaultExecutionOrder(ActionSystemConstDefine.ActionSystemManagerExcutionOrder)]
    public class ActionSystemManager : MonoBehaviour
    {        
        //系统配置文件
        [SerializeField]
        private TextAsset actionSystemConfig;
        [SerializeField]
        private TextAsset boxConflictConfig;

        private ActionSystemConfig sysConfig;
        private ActionSystemBoxConflictConfig boxConfig;
        [SerializeField]
        private bool is3DGame = true;
        [SerializeField]
        private bool unityFixedUpdateDisable = true;
        #region 单例
        private static ActionSystemManager _instance;      
        public static ActionSystemManager Instance
        {
            get {               
                return _instance;
            }
        }
        #endregion
        #region 系统配置
        float timer = 0;
        /// <summary>
        /// 导入配置
        /// </summary>
        /// <param name="sysConfig"></param>
        public void SetConfig(ActionSystemConfig sysConfig,ActionSystemBoxConflictConfig boxConfig)
        {
            this.sysConfig = sysConfig;
            this.sysConfig.InitInternalData();
            this.boxConfig = boxConfig;
            InitBoxSetting(this.boxConfig);
            //初始化map
        }
        public void SetConfig(TextAsset actionSystemConfig,TextAsset boxConflictConfig)
        {
            #region 系统设置
            this.actionSystemConfig = actionSystemConfig;
            //反序列化
            if (this.actionSystemConfig !=null)
            {                
                this.sysConfig = DataUtility.FromJson(this.actionSystemConfig.text, typeof(ActionSystemConfig)) as ActionSystemConfig;
            }            
            if (this.sysConfig == null)
            {
                this.sysConfig = new ActionSystemConfig();                
                Debug.LogWarning("使用默认的动作系统配置(ActionSystemConfig)");
            }
            this.sysConfig.InitInternalData();
            #endregion

            #region hitbox
            this.boxConflictConfig = boxConflictConfig;
            if(this.boxConflictConfig!=null)
            {
                this.boxConfig = DataUtility.FromJson(this.boxConflictConfig.text,typeof(ActionSystemBoxConflictConfig)) as ActionSystemBoxConflictConfig;
            }
            if (this.boxConfig == null)
            {
                this.boxConfig = new ActionSystemBoxConflictConfig();
                Debug.LogWarning("使用默认的动作系统碰撞盒配置(ActionSystemBoxConflictConfig)");
            }
            InitBoxSetting(this.boxConfig);
            #endregion
        }
        Dictionary<int, int> layerMap = new Dictionary<int, int>();
        Dictionary<int, int> antiLayerMap = new Dictionary<int, int>();
        Dictionary<int, int> layerMaskMap = new Dictionary<int, int>(); 
        void InitBoxSetting(ActionSystemBoxConflictConfig setting)
        {
            layerMap.Clear();
            antiLayerMap.Clear();
            layerMaskMap.Clear();
            if(setting.matrix.Count==0)
            {
                for(int i=0;i<=ActionSystemConstDefine.MaxLayer;i++)
                {
                    layerMap.Add(i,i);
                    antiLayerMap.Add(i,i);
                }
                for (int i = 0; i <= ActionSystemConstDefine.MaxLayer; i++)
                {
                    int mask = 0;
                    for (int j = 0; j <= ActionSystemConstDefine.MaxLayer; j++)
                    {
                        if(is3DGame)
                        {
                            if (!Physics.GetIgnoreLayerCollision(i,j))
                            {
                                mask |= 1 << layerMap[setting.matrix[j].boxType];
                            }
                        }
                        else
                        {
                            if (!Physics2D.GetIgnoreLayerCollision(i, j))
                            {
                                mask |= 1 << layerMap[setting.matrix[j].boxType];
                            }
                        }
                        
                    }
                    layerMaskMap.Add(i, mask);
                }
            }else
            {
                for (int i = 0; i < setting.matrix.Count; i++)
                {
                    if (!layerMap.ContainsKey(setting.matrix[i].boxType))
                    {
                        layerMap.Add(setting.matrix[i].boxType, setting.matrix[i].unityLayer);
                    }
                    else
                    {
                        Debug.LogError("Layer 配置重复");
                    }
                    if (!antiLayerMap.ContainsKey(setting.matrix[i].unityLayer))
                    {
                        antiLayerMap.Add(setting.matrix[i].unityLayer, setting.matrix[i].boxType);
                    }
                    else
                    {
                        Debug.LogError("unityLayer 配置重复");
                    }
                }
                for(int i=0;i<setting.matrix.Count;i++)
                {
                    int mask = 0;
                    for(int j=0;j< setting.matrix.Count; j++)
                    {
                        if((setting.matrix[i].boxMask&(1<< setting.matrix[j].boxType))!=0)
                        {
                            mask |= 1 << layerMap[setting.matrix[j].boxType];
                        }
                    }
                    if(!layerMaskMap.ContainsKey(setting.matrix[i].boxType))
                        layerMaskMap.Add(setting.matrix[i].boxType, mask);
                }
            }
        }
        public ActionSystemConfig GlobalConfig => sysConfig;
        
        #endregion
        #region UnityAPI
        private void Awake()
        {
            _instance = this;            
            //导入配置
            SetConfig(actionSystemConfig,boxConflictConfig);
            if(is3DGame)
            {
                Physics.autoSimulation = false;
            }
            else
            {
                Physics2D.autoSimulation = false;
            }
            if(unityFixedUpdateDisable)
            {
                Time.fixedDeltaTime = float.MaxValue;
            }
            DontDestroyOnLoad(this);
            //初始化Utils
            UtilsInit.InitDefalutGameObjectPool(sysConfig.poolItemTypes);



            Debug.Log(typeof(ActionSystemManager).Name+" inited");
        }
        bool destroyed = false;
        private void OnDestroy()
        {
            destroyed = true;
            Debug.Log(typeof(ActionSystemManager).Name + " destroyed");
        }
        private void Update()
        {

            if(sysConfig!=null)
            {
                //正常逻辑
                timer += Time.deltaTime;
                int loopCNT = 0;
                //float timeNow = Time.realtimeSinceStartup;
                //固定60帧更新一次
                while (timer > sysConfig.FrameTime)
                {
                    loopCNT += 1;
                    UpdateSM(sysConfig.FrameTime);
                    timer -= sysConfig.FrameTime;
                }
                //if(loopCNT>0)
                //{                    
                //    Debug.Log($"LOOPCNT {loopCNT} SM Excute Time:{1000*(Time.realtimeSinceStartup - timeNow)}ms");
                //}
                    
            }
            else
            {
                throw new System.Exception("ActionSystemManager没有设置配置文件");
            }

        }
        #endregion
        #region SM
        /// <summary>
        /// 60帧更新
        /// </summary>
        /// <param name="fixedDeltaTime">更新之间的时间差,固定</param>
        private void UpdateSM(float fixedDeltaTime)
        {

            #region 其他系统同步
            {
                //float timeNow = Time.realtimeSinceStartup;
                ManageBeforeSync();
                foreach (var bs in beforeSyncs)
                {
                    bs.Update(fixedDeltaTime);
                }
                //Debug.Log($"SM 其他系统同步 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 管理状态机
            {
                //float timeNow = Time.realtimeSinceStartup;                
                ManageSMs();
                //Debug.Log($"SM 管理状态机 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 更新帧数
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    sm.UpdateFrameIndex();
                }

                //Debug.Log($"SM 更新帧数 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 状态机之间关联数据
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    sm.UpdateRelationship();
                }
                //Debug.Log($"SM 状态机之间关联数据 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 状态机“内部状态数据”更新
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    sm.UpdateInnerData();
                }

                //Debug.Log($"SM 状态机“内部状态数据”更新 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion            
            #region 更新时间
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    sm.UpdateTime(fixedDeltaTime);
                }

                //Debug.Log($"SM 更新时间 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion            
            #region 更新状态
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    sm.UpdateState();
                }
                //Debug.Log($"SM 更新状态 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 更新HitBox
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IHitProcessAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetHitProcessAbility()?.OnHitBoxSetUp();
                    }
                }
                //Debug.Log($"SM 更新HitBox Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 处理动画
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {                
                    var abilityInferace = sm as IAnimationAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetAnimationAbility()?.BeforeAnimationEvaluate();
                    }
                }
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IAnimationAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetAnimationAbility()?.AnimationEvaluate();
                    }
                }
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IAnimationAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetAnimationAbility()?.AfterAnimationEvaluate();
                    }
                }
                //Debug.Log($"SM 处理动画 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 处理物理
            {
                //float timeNow = Time.realtimeSinceStartup;

                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IPhysicsAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetPhysicsAbility()?.PreSimulationUpdate(fixedDeltaTime);
                    }
                }
                if (is3DGame)
                {
                    Physics.Simulate(fixedDeltaTime);
                }else
                {
                    Physics2D.Simulate(fixedDeltaTime);
                }
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IPhysicsAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetPhysicsAbility()?.PostSimulationUpdate(fixedDeltaTime);
                    }
                }
                //Debug.Log($"SM 处理物理 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region IK
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IAnimationAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetAnimationAbility()?.IKSolve();
                    }
                }
                //Debug.Log($"SM IK Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 攻击检测
            {
                //float timeNow = Time.realtimeSinceStartup;

                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IHitProcessAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetHitProcessAbility()?.OnHitDetect();
                    }
                }
               // Debug.Log($"SM 攻击检测 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 处理逻辑
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IActiveLogicAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetActiveLogicAbility()?.ActiveLogicActionUpdate();
                    }
                }
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IActiveLogicAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetActiveLogicAbility()?.PostActiveLogicActionUpdate();
                    }
                }

                //Debug.Log($"SM 处理逻辑 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 被动逻辑
            {
                //float timeNow = Time.realtimeSinceStartup;

                foreach (var sm in SMs)
                {
                    sm.PassiveLogicActionUpdate();
                }
                //Debug.Log($"SM 被动逻辑 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 受击处理
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    var abilityInferace = sm as IHitProcessAbility;
                    if (abilityInferace != null)
                    {
                        abilityInferace.GetHitProcessAbility()?.HitProcess();
                    }
                }

                //Debug.Log($"SM 受击处理 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 重置数据
            {
                //float timeNow = Time.realtimeSinceStartup;
                foreach (var sm in SMs)
                {
                    sm.ResetInnerData();
                }

                //Debug.Log($"SM 重置数据 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
            #region 其他系统同步
            {
                //float timeNow = Time.realtimeSinceStartup;
                ManageAfterSync();
                foreach (var asy in afterSyncs)
                {
                    asy.Update(fixedDeltaTime);
                }

                //Debug.Log($"------SM 其他系统同步 Time:{1000 * (Time.realtimeSinceStartup - timeNow)}ms");
            }
            #endregion
        }
        public static float FrameTime
        {
            get
            {
                if(Instance.GlobalConfig==null)
                {
                    throw new System.Exception("ActionSystemManager没有设置配置文件");
                }    
                return Instance.GlobalConfig.FrameTime;
            }
        }
        HashSet<BaseStateMachine> wantedInit = new HashSet<BaseStateMachine>();
        HashSet<BaseStateMachine> SMs = new HashSet<BaseStateMachine>();
        HashSet<BaseStateMachine> wantedDestroy = new HashSet<BaseStateMachine>();

        HashSet<IActionSystemSync> beforeSyncsAdd = new HashSet<IActionSystemSync>();
        HashSet<IActionSystemSync> beforeSyncs = new HashSet<IActionSystemSync>();
        HashSet<IActionSystemSync> beforeSyncsRemove = new HashSet<IActionSystemSync>();

        HashSet<IActionSystemSync> afterSyncsAdd = new HashSet<IActionSystemSync>();
        HashSet<IActionSystemSync> afterSyncs = new HashSet<IActionSystemSync>();
        HashSet<IActionSystemSync> afterSyncsRemove = new HashSet<IActionSystemSync>();
        /// <summary>
        /// 系统更新之前需要同步的，比如输入
        /// </summary>
        /// <param name="module">同步模块</param>
        public void AddBeforeSync(IActionSystemSync module)
        {
            if(module != null&&!beforeSyncs.Contains(module))
            {
                beforeSyncsAdd.Add(module);
            }
        }
        private void ManageBeforeSync()
        {
            //清除
            if (beforeSyncsRemove.Count > 0)
            {
                foreach (var bs in beforeSyncsRemove)
                {
                    if (beforeSyncs.Contains(bs))
                    {
                        beforeSyncs.Remove(bs);
                    }
                }
                beforeSyncsRemove.Clear();
            }
            //添加
            if (beforeSyncsAdd.Count > 0)
            {
                foreach (var bs in beforeSyncsAdd)
                {
                    if (!beforeSyncs.Contains(bs))
                    {
                        beforeSyncs.Add(bs);
                    }
                }
                beforeSyncsAdd.Clear();
            }
        }
        /// <summary>
        /// 清除同步模块
        /// </summary>
        /// <param name="module"></param>
        public void RemoveBeforeSync(IActionSystemSync module)
        {
            if (module != null&&beforeSyncs.Contains(module))
            {
                beforeSyncsRemove.Add(module);
            }
        }        
        /// <summary>
        /// 系统更新之后同步
        /// </summary>
        /// <param name="module">同步模块</param>
        public void AddAfterSync(IActionSystemSync module)
        {
            if (module != null && !afterSyncs.Contains(module))
            {
                afterSyncsAdd.Add(module);
            }
        }
        private void ManageAfterSync()
        {
            //清除
            if (afterSyncsRemove.Count > 0)
            {
                foreach (var bs in afterSyncsRemove)
                {
                    if (afterSyncs.Contains(bs))
                    {
                        afterSyncs.Remove(bs);
                    }
                }
                afterSyncsRemove.Clear();
            }
            //添加
            if (afterSyncsAdd.Count > 0)
            {
                foreach (var bs in afterSyncsAdd)
                {
                    if (!afterSyncs.Contains(bs))
                    {
                        afterSyncs.Add(bs);
                    }
                }
                afterSyncsAdd.Clear();
            }
        }
        /// <summary>
        /// 清除同步模块
        /// </summary>
        /// <param name="module"></param>
        public void RemoveAfterSync(IActionSystemSync module)
        {
            if (module != null && afterSyncs.Contains(module))
            {
                afterSyncsRemove.Add(module);
            }
        }
        private void ManageSMs()
        {
            //清除
            if (wantedDestroy.Count > 0)
            {
                foreach (var w in wantedDestroy)
                {
                    if (SMs.Contains(w))
                    {
                        w.Destroy();
                        SMs.Remove(w);
                    }
                }
                wantedDestroy.Clear();
            }
            //添加
            if (wantedInit.Count>0)
            {
                foreach(var w in wantedInit)
                {
                    if(!SMs.Contains(w))
                    {
                        w.ResetMachine();
                        SMs.Add(w);
                    }                    
                }
                wantedInit.Clear();
            }
        }
        public void Register(BaseStateMachine sm)
        {
            if (destroyed)
            {
                return;
            }
            if (sm == null)
            {
                Debug.Log("状态机为空");
                return;
            }
            if (!wantedInit.Contains(sm))
            {
                wantedInit.Add(sm);
                sm.InstanceMachine();
            }
            else
            {
                Debug.Log(sm.name + " 状态机已注册");
            }
        }
        public void DestroySM(BaseStateMachine sm)
        {
            if(destroyed)
            {
                return;
            }
            if (sm == null)
            {
                Debug.Log("状态机为空");
                return;
            }
            if (!wantedDestroy.Contains(sm))
            {
                wantedDestroy.Add(sm);
            }
            else
            {
                Debug.Log(sm.name + " 状态机已销毁");
            }
        }
        public BaseStateMachine GetStateMachine(Transform root)
        {
            foreach (var sm in SMs)
            {
                if (sm.transform == root)
                {
                    return sm;
                }
            }
            return null;
        }
        /// <summary>
        /// 获取boxType对应的Layer
        /// </summary>
        /// <param name="boxType"></param>
        /// <returns></returns>
        public int GetUnityLayer(int boxType)
        {
            if(layerMap.TryGetValue(boxType,out int res))
            {
                return res;
            }
            else
            {
                return ActionSystemConstDefine.InValidLayer;
            }
        }
        /// <summary>
        /// 获取BoxType
        /// </summary>
        /// <param name="unityLayer">Unity的Layer</param>
        /// <returns></returns>
        public int GetBoxType(int unityLayer)
        {
            if (antiLayerMap.TryGetValue(unityLayer,out int res))
            {
                return res;
            }
            else
            {
                return ActionSystemConstDefine.InValidLayer;
            }
        }
        /// <summary>
        /// 获取boxType可以检测的LayerMask
        /// </summary>
        /// <param name="boxType"></param>
        /// <returns></returns>
        public int GetUnityLayerMask(int boxType)
        {
            layerMaskMap.TryGetValue(boxType, out int res);            
            return res;
        }
        
        #endregion
    }
}

